package com.generalbackend.common.util;

import org.springframework.cglib.beans.BeanCopier;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author tim.xie
 * @date 2022/1/5 16:00
 */
public class BeanCopierUtils {

    private static final Map<String, BeanCopier> BEAN_COPIER_MAP = new ConcurrentHashMap<>();

    /**
     * 拷贝属性
     * @param source
     * @param target
     */
    public static void copyProperties(Object source, Object target) {
        if (source != null && target != null) {
            String beanKey = generateKey(source.getClass(), target.getClass());
            BeanCopier beanCopier = BEAN_COPIER_MAP.get(beanKey);
            if(beanCopier == null) {
                beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
                BEAN_COPIER_MAP.put(beanKey, beanCopier);
            }
            beanCopier.copy(source, target, null);
        }
    }

    /**
     * 拷贝对象
     * @param source
     * @param target
     * @param <T>
     * @return
     */
    public static <T> T copyOne2One(Object source, Class<T> target) {
        if (source != null && target != null) {
            T instance = null;
            try {
                instance = target.newInstance();
                copyProperties(source, instance);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return instance;
        }
        return null;
    }

    /**
     * 拷贝集合
     * @param source
     * @param target
     * @param <T>
     * @return
     */
    public <T> List<T> copyList2List(List<?> source, Class<T> target) {
        if (source != null && target != null) {
            if (source.isEmpty()) {
                return new ArrayList<>();
            } else {
                List<T> result = new ArrayList<>();
                Iterator<?> iterator = source.iterator();
                while (iterator.hasNext()) {
                    Object obj = iterator.next();
                    result.add(copyOne2One(obj, target));
                }
                return result;
            }
        }
        return null;
    }

    /**
     * 根据两个class生成key
     * @param class1
     * @param class2
     * @return
     */
    private static String generateKey(Class<?> class1, Class<?> class2) {
        return new StringBuilder().append(class1.toString()).append(class2.toString()).toString();
    }

}
